package com.mysterymall.Service.Impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mysterymall.Common.Comp.HttpStatus;
import com.mysterymall.Common.Comp.LocalCache;
import com.mysterymall.Common.Utils.Result;
import com.mysterymall.Common.Utils.BaseEnum;
import com.mysterymall.Common.Utils.StringUtils;
import com.mysterymall.Mapper.*;
import com.mysterymall.Model.Dto.LoginDto;
import com.mysterymall.Model.Dto.UserDto;
import com.mysterymall.Model.Entity.*;
import com.mysterymall.Model.Vo.UserVo;
import com.mysterymall.Service.SmsService;
import com.mysterymall.Service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName com.mysterymall.Service.Impl
 * @Description
 * @Author HuangWX
 * @Time 2023/11/04  00:12
 */
@Service
public class UserServiceImpl implements UserService {

    private final UserMapper userMapper;

    private final RoleMapper roleMapper;

    private final TeamMapper teamMapper;

    private final SmsService smsService;

    private final AddressMapper addressMapper;

    private final OperationRecordsMapper operationRecordsMapper;

    /**
     * 构造器注入
     *
     * @param userMapper 用户映射器
     * @param roleMapper 角色映射器
     * @param teamMapper 队伍映射器
     * @param smsService 短信服务
     * @param addressMapper 地址映射器
     */
    public UserServiceImpl(UserMapper userMapper, RoleMapper roleMapper, TeamMapper teamMapper, SmsService smsService,
                           AddressMapper addressMapper,OperationRecordsMapper operationRecordsMapper) {
        this.userMapper = userMapper;
        this.roleMapper = roleMapper;
        this.teamMapper = teamMapper;
        this.smsService = smsService;
        this.addressMapper = addressMapper;
        this.operationRecordsMapper = operationRecordsMapper;
    }

    @Value("${mystery.rootPath}")
    private String rootPath;


    @Override
    public Result login(LoginDto loginDto) {

        User user = userMapper.queryByUserName(loginDto.getUserName());

        if (user == null)
            return new Result(HttpStatus.BAD_NOT_PASS, "message.userCont.login.error");


        Object o = LocalCache.CACHE.get("loginErrorNumber-" + user.getId());

        if (o != null) {
            Integer i = (Integer) o;
            if (i >= 5)
                return new Result(HttpStatus.BAD_NOT_PASS, "message.userCont.login.error");
        }

        String password = SaSecureUtil.aesDecrypt(BaseEnum.passwordSlats.getCode(), user.getPassword());

        if (password.equals(loginDto.getPassword())) {

            if(StpUtil.isDisable(user.getId()) || user.getStatus() ==1 ){
                return new Result(HttpStatus.BAD_NOT_PASS, "message.userCont.login.accountLock");
            }

            StpUtil.login(user.getId());

            LocalCache.CACHE.put("loginErrorNumber-" + user.getId(), 0, 1);
            Map<String, Object> result = new HashMap<>();

            UserVo userView = new UserVo();

            BeanUtils.copyProperties(user, userView);

            userView.setNotes(roleMapper.selectById(user.getRoleId()).getType());

            result.put("MysteryAuth", StpUtil.getTokenValue());
            result.put("userData", userView);
            return new Result(HttpStatus.SUCCESS, "message.userCont.login.success", result);
        } else {
            if (o != null) {
                Integer i = (Integer) o;
                i++;
                LocalCache.CACHE.put("loginErrorNumber-" + user.getId(), i, 3600000);
                if (5 - i != 0) {
                    return new Result(HttpStatus.BAD_NOT_PASS, "message.userCont.login.error", 5 - i + "");
                } else {
                    return new Result(HttpStatus.BAD_NOT_PASS, "message.userCont.login.accountLock");
                }
            }
            LocalCache.CACHE.put("loginErrorNumber-" + user.getId(), 1, 3600000);
            return new Result(HttpStatus.BAD_NOT_PASS, "message.userCont.login.error");
        }
    }

    @Override
    public Result addUser(UserDto userDto) {

        User user = new User();

        // 查询是否有重复的用户名
        if(userMapper.queryByUserName(userDto.getUserName()) != null){
            return new Result(HttpStatus.BAD_NOT_PASS,"message.userCont.register.repeatError");
        }

        // 用户名
        user.setUserName(userDto.getUserName());

        // 密码
        String ciphertext = SaSecureUtil.aesEncrypt(BaseEnum.passwordSlats.getCode(),userDto.getPassword());

        user.setPassword(ciphertext);

        // 用户权限
        if(userDto.getRoleType().equals("user")){
            user.setRoleId(roleMapper.queryByType(BaseEnum.User.getCode()).getId());
        }else if(userDto.getRoleType().equals("admin")){
            user.setRoleId(roleMapper.queryByType(BaseEnum.Admin.getCode()).getId());
        }else{
            user.setRoleId(roleMapper.queryByType(BaseEnum.User.getCode()).getId());
        }

        // 余额
        user.setAmount(new BigDecimal(0));

        // 佣金余额
        user.setBrokerage(new BigDecimal(0));


        // 昵称
        user.setNickname(userDto.getUserName());

        // 基础比例
        user.setScale(new BigDecimal(BaseEnum.Commission_Rate.getCode()));

        // 默认头像
        user.setUserImages(BaseEnum.Default_Head_Portrait.getCode());

        user.setStatus(0);

        // 邀请码(自己的邀请码)
        String invitationCode = StringUtils.getRandom(6);
        if (userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getInvitationCode, invitationCode)) == null) {
            user.setInvitationCode(invitationCode);
        } else {
            user.setInvitationCode(StringUtils.getRandom(6));
        }

        // 创建用户
        userMapper.insert(user);

        OperationRecords operationRecords = new OperationRecords();

        operationRecords.setUserId(StpUtil.getLoginIdAsString());

        operationRecords.setContent("添加了用户名为" + user.getUserName() + "的用户");

        operationRecordsMapper.insert(operationRecords);

        return new Result(HttpStatus.SUCCESS,"message.addSuccess");
    }

    @Override
    public Result registration(LoginDto loginDto, HttpServletRequest request) throws IOException {

        // 用户名重复校验
        if (userMapper.queryByUserName(loginDto.getUserName()) != null) {
            return new Result(HttpStatus.BAD_NOT_PASS, "message.userCont.register.repeatError");
        }

        // 验证码校验
        if(!smsService.verifySms(loginDto.getCode(),request.getSession().getId())){
            return new Result(HttpStatus.BAD_NOT_PASS, "message.SmsCont.smsCode.error");
        }

        User user = new User();
        user.setUserName(loginDto.getUserName());

        // 密码加密
        String salt = "c90be4fc-1389-a34a-b94a-c497f3acf5e8";
        String ciphertext = SaSecureUtil.aesEncrypt(salt, loginDto.getPassword());
        user.setPassword(ciphertext);


        // 用户权限
        Role role = roleMapper.queryByType(BaseEnum.User.getCode());
        user.setRoleId(role.getId());

        // 余额
        user.setAmount(new BigDecimal(0));

        // 佣金余额
        user.setBrokerage(new BigDecimal(0));

        // 昵称
        user.setNickname(loginDto.getUserName());

        // 基础比例
        user.setScale(new BigDecimal(BaseEnum.Commission_Rate.getCode()));

        // 默认头像
        user.setUserImages(BaseEnum.Default_Head_Portrait.getCode());

        user.setStatus(0);

        // 邀请码(自己的邀请码)
        String invitationCode = StringUtils.getRandom(6);
        if (userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getInvitationCode, invitationCode)) == null) {
            user.setInvitationCode(invitationCode);
        } else {
            user.setInvitationCode(StringUtils.getRandom(6));
        }

        // 创建用户
        userMapper.insert(user);

        // 邀请码
        if (loginDto.getInvitationCode() != null && !loginDto.getInvitationCode().isEmpty()) {
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(User::getInvitationCode, loginDto.getInvitationCode());
            User user1 = userMapper.selectOne(queryWrapper);
            if (user1 != null) {
                Team team = new Team();

                // 邀请人的ID
                team.setCreateUser(user1.getId());

                // 被邀请人的ID
                team.setUserId(user.getId());

                // 累计充值金额
                team.setAccumulateAmount(new BigDecimal(0));

                teamMapper.insert(team);
            }
        }

        StpUtil.login(user.getId());
        Map<String, Object> result = new HashMap<>();
        UserVo userView = new UserVo();
        BeanUtils.copyProperties(user, userView);

        result.put("MysteryAuth", StpUtil.getTokenValue());
        result.put("userData", userView);
        return new Result(HttpStatus.SUCCESS, "message.userCont.register.success", result);
    }

    @Override
    public Result userInfo() {
        if (StpUtil.isLogin()) {
            User user = userMapper.selectById(StpUtil.getLoginId().toString());
            UserVo userVo = new UserVo();
            BeanUtils.copyProperties(user, userVo);
            userVo.setUserImages("/images/" + user.getUserImages());
            return new Result(HttpStatus.SUCCESS, "message.querySuccess", userVo);
        }
        return Result.error("message.powerError");
    }

    @Override
    public Result changeInfo(UserDto userDto) {


        User user = userMapper.selectById(StpUtil.getLoginId().toString());

        if (userDto.getBirthday() != null && !userDto.getBirthday().isEmpty()) {
            user.setBirthday(Instant.parse(userDto.getBirthday()));
        }
        userDto.setAmount(user.getAmount());

        if (userDto.getMailbox() != null) {
            user.setMailbox(userDto.getMailbox());
        }

        if (userDto.getAddress() != null) {
            user.setAddress(userDto.getAddress());
        }

        if (userDto.getNickname() != null) {
            user.setNickname(userDto.getNickname());
        }

        if (userDto.getUserImages() != null) {
            File images = new File(rootPath + user.getUserImages());
            images.delete();
            user.setUserImages(userDto.getUserImages());
        }

        if (userDto.getSex() != null) {
            user.setSex(userDto.getSex());
        }



        userMapper.updateById(user);

        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(user, userVo);
        userVo.setUserImages("/images/" + user.getUserImages());
        return Result.success("message.updateSuccess", userVo);
    }

    @Override
    public Result changePassword(LoginDto loginDto) {

        User user = userMapper.selectById(StpUtil.getLoginId().toString());

        String password = SaSecureUtil.aesDecrypt(BaseEnum.passwordSlats.getCode(), user.getPassword());

        if (!password.equals(loginDto.getUserName())) {
            return Result.error(HttpStatus.BAD_NOT_PASS, "message.userCont.login.error");
        }

        String ciphertext = SaSecureUtil.aesEncrypt(BaseEnum.passwordSlats.getCode(), loginDto.getPassword());

        user.setPassword(ciphertext);

        userMapper.updateById(user);

        return Result.success("message.updateSuccess");
    }

    @Override
    public Result getAllUser(Integer page, Integer size) {

        if (!StpUtil.hasPermission("user:select:*")) {
            return new Result(HttpStatus.UNAUTHORIZED, "message.powerError");
        }

        Page<User> userPage = userMapper.selectPage(new Page<>(page, size), new LambdaQueryWrapper<User>().orderByDesc(User::getCreateTime));


        List<UserVo> userVoList = new ArrayList<>(size);

        for (User user : userPage.getRecords()) {
            UserVo userVo = new UserVo();
            BeanUtils.copyProperties(user, userVo);
            // 游戏币
            userVo.setAmount(user.getAmount().multiply(new BigDecimal(10)));
            // 将佣金比例转换为百分比
            userVo.setScale(user.getScale().multiply(new BigDecimal(100)));
            userVo.setCreateTime(user.getCreateTime().toString());
            userVo.setUserImages("/images/" + user.getUserImages());
            userVo.setNotes(SaSecureUtil.aesDecrypt(BaseEnum.passwordSlats.getCode(), user.getPassword()));
            userVoList.add(userVo);
        }

        Map<String, Object> map = new HashMap<>(2);
        map.put("userList", userVoList);
        map.put("total", userPage.getTotal());

        return Result.success("message.querySuccess", map);
    }

    @Override
    public Result userInfoFuzzySearch(String search) {

        if (!StpUtil.hasPermission("user:select:*")) {
            return new Result(HttpStatus.UNAUTHORIZED, "message.powerError");
        }

        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();

        lambdaQueryWrapper.like(User::getUserName, search).or().like(User::getNickname, search);

        List<User> userList = userMapper.selectList(lambdaQueryWrapper);

        List<UserVo> userVoList = new ArrayList<>(userList.size());

        for (User user : userList) {
            UserVo userVo = new UserVo();
            BeanUtils.copyProperties(user, userVo);
            userVo.setCreateTime(user.getCreateTime().toString());
            // 游戏币
            userVo.setAmount(user.getAmount().multiply(new BigDecimal(10)));
            // 将佣金比例转换为百分比
            userVo.setScale(user.getScale().multiply(new BigDecimal(100)));
            userVo.setUserImages("/images/" + user.getUserImages());
            userVoList.add(userVo);
        }
        Map<String, Object> map = new HashMap<>(2);
        map.put("userList", userVoList);
        map.put("total", userList.size());
        return Result.success("message.querySuccess", map);
    }

    @Override
    public Result updateUserInfo(UserDto userDto) {

        if (!StpUtil.hasPermission("user:update:*")) {
            return new Result(HttpStatus.UNAUTHORIZED, "message.powerError");
        }

        User user = userMapper.selectById(userDto.getId());

        if (user == null) {
            return new Result(HttpStatus.BAD_REQUEST, "message.updateError");
        }

        OperationRecords operationRecords = new OperationRecords();

        operationRecords.setUserId(StpUtil.getLoginIdAsString());

        user.setNickname(userDto.getNickname());

        // 抽佣比例
        if (userDto.getScale() != null && userDto.getScale().compareTo(new BigDecimal(0)) >= 0 && userDto.getScale().compareTo(new BigDecimal(100)) <= 0) {
            // 将百分比转换为小数,保留两位小数
            user.setScale(userDto.getScale().divide(new BigDecimal(100)));
        }

        // 金额
        if(userDto.getAmount().compareTo(new BigDecimal(0)) >= 0){
            // 将金额除去10倍
            user.setAmount(userDto.getAmount().divide(new BigDecimal(10),2, RoundingMode.HALF_UP));
            operationRecords.setContent("修改了用户名为" + user.getUserName() + "的游戏币余额为" + userDto.getAmount());
        }
        operationRecordsMapper.insert(operationRecords);

        operationRecords = new OperationRecords();
        operationRecords.setUserId(StpUtil.getLoginIdAsString());
        // 佣金
        if(userDto.getBrokerage().compareTo(new BigDecimal(0)) >= 0){
            // 将佣金除去10倍
            user.setBrokerage(userDto.getBrokerage());
            operationRecords.setContent("修改了用户名为" + user.getUserName() + "的佣金余额为" + userDto.getBrokerage());
        }
        operationRecordsMapper.insert(operationRecords);
        userMapper.updateById(user);

        return Result.success("message.updateSuccess");
    }

    @Override
    public Result getBalance() {

        User user = userMapper.selectById(StpUtil.getLoginId().toString());

        Map<String,Object> map = new HashMap<>(2);

        map.put("balance",user.getAmount().multiply(new BigDecimal(10)));
        map.put("brokerage",user.getBrokerage().multiply(new BigDecimal(10)));

        return Result.success("message.querySuccess",map);
    }

    @Override
    public Result getMyAddress() {

        User user = userMapper.selectById(StpUtil.getLoginId().toString());

        Address address =  addressMapper.selectById(user.getAddress());

        if(address == null){
            return new Result(HttpStatus.BAD_REQUEST,"message.queryError");
        }

        return new Result(HttpStatus.SUCCESS,"message.querySuccess",address);
    }

    @Override
    public Result getAdminList() {
        // 查询全部管理员
        List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getRoleId,roleMapper.queryByType(BaseEnum.Admin.getCode()).getId()));

        // 加一个超级管理员
        userList.addAll(userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getRoleId,roleMapper.queryByType(BaseEnum.Super_Admin.getCode()).getId())));

        List<UserVo> userVoList = new ArrayList<>(userList.size());

        for (User user : userList) {
            UserVo userVo = new UserVo();
            BeanUtils.copyProperties(user, userVo);
            userVo.setCreateTime(user.getCreateTime().toString());
            // 游戏币
            userVo.setAmount(user.getAmount().multiply(new BigDecimal(10)));
            // 将佣金比例转换为百分比
            userVo.setScale(user.getScale().multiply(new BigDecimal(100)));
            userVo.setUserImages("/images/" + user.getUserImages());
            userVoList.add(userVo);
        }
        Map<String, Object> map = new HashMap<>(2);
        map.put("userList", userVoList);
        map.put("total", userList.size());
        return Result.success("message.querySuccess", map);
    }

    @Override
    public Result getAdminLog(Integer page, Integer size, String userId) {

        // 查询用户
        User user = userMapper.selectById(userId);

        if(user == null){
            return new Result(HttpStatus.BAD_REQUEST,"message.queryError");
        }

        // 查询操作记录
        Page<OperationRecords> operationRecordsPage = operationRecordsMapper.selectPage(new Page<>(page, size), new LambdaQueryWrapper<OperationRecords>().eq(OperationRecords::getUserId, userId).orderByDesc(OperationRecords::getCreateTime));


        //将用户ID改为用户名
        for (OperationRecords operationRecords : operationRecordsPage.getRecords()) {
            operationRecords.setUserId(userMapper.selectById(operationRecords.getUserId()).getUserName());
        }


        return new Result(HttpStatus.SUCCESS,"message.querySuccess",operationRecordsPage);

    }


}
